﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Needle.Framework;
using SCM = System.ComponentModel;
using SCMD = System.ComponentModel.Design;
using Needle.DevToolkit.Traits;
using Needle.Utils.Extensions;
namespace Needle.DevToolkit.Services.UI
{
 
    public class CommandService : ServiceBase, ICommandService
    {

        private static readonly ItemVerb[] EmptyVerbs = new ItemVerb[] { };

        private Dictionary<SCM.IComponent, List<ItemVerb>> _verbs;

        public CommandService(IServiceProvider serviceProvider)
            : base(serviceProvider)
        {
            _verbs = new Dictionary<System.ComponentModel.IComponent, List<ItemVerb>>();
        }

        public void AddVerbs(SCM.IComponent component)
        {
            if (component == null)
                throw new ArgumentNullException("component", "component is null.");

            List<ItemVerb> componentVerbs = null;
            if (_verbs.TryGetValue(component, out componentVerbs))
                throw new InvalidOperationException("Verbs for this component already added");

            componentVerbs = new List<ItemVerb>(VerbAttribute.GetVerbs(component));
            _verbs.Add(component, componentVerbs);
            component.Disposed += (sender, e) => RemoveVerbs((SCM.IComponent)sender);
        }

        public void RemoveVerbs(SCM.IComponent component)
        {
            if (component == null)
                throw new ArgumentNullException("component", "component is null.");
            List<ItemVerb> myVerbs=null;
            if (_verbs.TryGetValue(component,out myVerbs))
            {
                myVerbs.ForEach(x => x.Supported = x.Enabled = x.Visible = false);
                _verbs.Remove(component);
            }
        }

        public IList<ItemVerb> GetCommands(Guid menuGroup)
        {
            if (_verbs == null)
                return EmptyVerbs;

            var allVerbs = (from IEnumerable<ItemVerb> verbs in _verbs.Values
                            select verbs).Flatten();
            
            return (from verb in allVerbs
                    where verb.CommandID.Guid == menuGroup
                    select verb).ToList();
        }

        public IList<ItemVerb> GetContextCommands(Guid menuGroup, object item)
        {
            if (_verbs == null)
                return EmptyVerbs;

            var allVerbs = (from IEnumerable<ItemVerb> verbs in _verbs.Values
                            select verbs).Flatten();

            return (from verb in allVerbs
                    where verb.CommandID.Guid == menuGroup && verb.CanOperateOn(item)
                    select verb).ToList();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _verbs.Clear();
            }
            base.Dispose(disposing);
        }


        protected override Type[] ExposedServices
        {
            get { return new Type[] { typeof(ICommandService) }; }
        }
    }
}
